package com.xhc.demo.controller;
import com.xhc.demo.utils.Utils;
import com.xhc.demo.dto.*;
import com.xhc.demo.GlobalConfig;
import com.xhc.demo.entity.*;
import com.xhc.demo.repository.*;
import com.xhc.demo.service.*;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.xhc.demo.utils.SnowflakeIdGenerator;
import jakarta.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.stream.Collectors;
import java.util.concurrent.atomic.AtomicLong;

@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = {"http://localhost:8080", "http://192.168.31.127:8080" , "http://p.mrxxhc.cn/" , "https://p.mrxxhc.cn/"}, allowCredentials = "true")
public class UserController {
    
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private AddressRepository addressRepository;
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private PhotoRepository photoRepository;
    
    @Autowired
    private PhotoAccessLogRepository photoAccessLogRepository;
    
    @Autowired
    private WeChatService weChatService;
    
    @Autowired
    private WxPayService wxPayService;
    
    @Autowired
    private SnowflakeIdGenerator snowflakeIdGenerator;

    @GetMapping("/all")
    public String getAllUsers() {
        return "test helloworld";
    } 
    
    @PostMapping("/wx_login")
    @ResponseBody
    public String wxLogin(@RequestBody WxLoginRequest request) {
        //session_key 过期的逻辑还没处理。
        String result = weChatService.getOpenId(request.getCode());
        logger.info("wxresult -> " + result);
        if (result.contains("openid")) { 
            JSONObject jsonObject = new JSONObject(result);
            String openid = jsonObject.getString("openid");
            String session_key = jsonObject.getString("session_key");
            String token = UUID.randomUUID().toString().replaceAll("-", "");
            User user = userRepository.findByOpenid(openid);
            if (user == null) {
                user = new User();
                // 处理 maxUserId 为 0 的情况
                if (GlobalConfig.maxUserId.get() == 0) {
                    // 尝试从数据库获取最大用户ID
                    Long maxId = userRepository.findMaxUserId();
                    GlobalConfig.maxUserId.set(maxId != null ? maxId : 0);
                }
                
                // 生成新的用户ID
                long newUserId = GlobalConfig.maxUserId.incrementAndGet();
                
                // 使用递增的 maxUserId 生成用户昵称
                user.setNickname("用户_" + newUserId);
                user.setOpenid(openid);
            }

            user.setSessionKey(session_key);
            user.setToken(token);
            userRepository.save(user);
          
            JSONObject response = new JSONObject();
            response.put("token", token);
            response.put("nickname", user.getNickname());
            logger.info("wxresult do -> " + response.toString());
            return Utils.getResponseJson(response);
        } else {
             logger.info("wxresult login_fail  ");
            return Utils.getErrorJson(400, "login_fail");
        }
    }

    // @PostMapping("/decryptedData_ex")
    // public String decryptedDataEx(@RequestBody Map<String, String> request) {
    //     String token = request.get("token");
    //     String encryptedData = request.get("encryptedData");

    //     // 验证 token
    //     User user = userRepository.findByToken(token);
    //     if (user == null) {
    //         return new JSONObject().put("error","Invalid token").toString();
    //     }

    //     // 使用 session_key 解密数据
    //     String sessionKey = user.getSessionKey();
    //     // 假设有一个解密方法 decryptData
    //     String decryptedData = null;
    //     try {
    //         decryptedData = decryptData(sessionKey, encryptedData);
    //         // 返回昵称和头像信息
    //         logger.info("解密后 -> " + decryptedData);
    //         JSONObject jsonResponse = new JSONObject(decryptedData);
    //         String nickname = jsonResponse.getString("nickname");
    //         String avatar = jsonResponse.getString("avatar");

    //         JSONObject response = new JSONObject();
    //         response.put("nickname", nickname);
    //         response.put("avatar", avatar);

    //         return response.toString();
    //     } catch (Exception e) {
    //         logger.info("e -> " + e.getMessage());
    //         e.printStackTrace();
    //     }

    //     return new JSONObject().put("error","fail").toString();
    // }

    // // 假设有一个解密方法 decryptData
    // private String decryptData(String sessionKey, String encryptedData) throws Exception {
    //     // Base64 decode
    //     byte[] encryptedDataBytes = Base64.getDecoder().decode(encryptedData);
    //     byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);

    //     // Initialize AES cipher
    //     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
    //     SecretKeySpec keySpec = new SecretKeySpec(sessionKeyBytes, "AES");
    //     IvParameterSpec iv = new IvParameterSpec(sessionKeyBytes, 0, 16);
    //     cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);

    //     // Decrypt data
    //     byte[] decryptedBytes = cipher.doFinal(encryptedDataBytes);
    //     return new String(decryptedBytes, StandardCharsets.UTF_8);
    // }

    @PostMapping("/getUploadToken")
    public String getUploadToken(@RequestBody Map<String, String> request) {
        
        String token = request.get("token");

        // 验证 token
        User user = userRepository.findByToken(token);
        if (user == null) {
            return new JSONObject().put("error", "Invalid token").toString();
        }
        // 生成七牛上传 token
        String uploadToken = Utils.getUploadToken();
        // 返回上传 token
        return Utils.getResponseJson(uploadToken);
    }

    

    @GetMapping("/get_my_all_address")
    public String getMyAllAddress(@RequestParam String token) {
        // 验证token
        if (token == null || token.trim().isEmpty()) {
            return Utils.getErrorJson(400, "Token is required");
        }

        // 查找用户
        User user = userRepository.findByToken(token);
        if (user == null || user.getUserId() == null) {
            return Utils.getErrorJson(401, "Invalid token");
        }

        // 获取用户的所有地址
        List<Address> addresses = addressRepository.findByUser(user);
        
        // 如果没有地址，返回空列表
        if (addresses == null) {
            addresses = Collections.emptyList();
        }

        // 构建返回数据
        List<Map<String, Object>> addressList = addresses.stream()
                .map(address -> {
                    Map<String, Object> addressMap = new HashMap<>();
                    addressMap.put("addressId", address.getAddressid());
                    addressMap.put("province", address.getProvince());
                    addressMap.put("city", address.getCity());
                    addressMap.put("district", address.getDistrict());
                    addressMap.put("detailAddress", address.getDetailAddress());
                    addressMap.put("phoneNumber", address.getPhoneNumber());
                    addressMap.put("consignee", address.getConsignee());
                    addressMap.put("isDefault", address.isDefault());
                    return addressMap;
                })
                .collect(Collectors.toList());

        return Utils.getResponseJson(addressList);
    }

    @PostMapping("/add_address")
    @Transactional
    public String addAddress(@RequestBody Map<String, Object> addressDetails) {
        String token = null;
        if(addressDetails.get("token") == null){
            return Utils.getErrorJson(400, "Missing token fields");
        }
       
        token = (String) addressDetails.get("token");
        User user = userRepository.findByToken(token);
        if (user == null || user.getUserId() == null) {
            return Utils.getErrorJson(401, "Invalid token");
        }
        
        // Validate address fields
        if (addressDetails.get("province") == null || addressDetails.get("city") == null ||
            addressDetails.get("district") == null || addressDetails.get("detail_address") == null ||
            addressDetails.get("phone_number") == null || addressDetails.get("consignee") == null) {
            return Utils.getErrorJson(400, "Missing required address fields");
        }

        Address address = new Address();
        address.setProvince((String) addressDetails.get("province"));
        address.setCity((String) addressDetails.get("city"));
        address.setDistrict((String) addressDetails.get("district"));
        address.setDetailAddress((String) addressDetails.get("detail_address"));
        address.setPhoneNumber((String) addressDetails.get("phone_number"));
        address.setConsignee((String) addressDetails.get("consignee"));
        
        Boolean isDefault = (Boolean) addressDetails.get("is_default");
        address.setDefault(isDefault != null && isDefault);
        address.setUser(user);

        // Save the address first to get the ID
        address = addressRepository.save(address);

        // If this is a default address, update other addresses
        if (address.isDefault()) {
            addressRepository.updateOtherAddressesDefaultStatus(user.getUserId(), address.getAddressid());
        }

        logger.info("address save -> " + address.toString());
        return Utils.getResponseJson("Address added successfully");
    }

    @PostMapping("/setdefault_address")
    @Transactional
    public String setDefaultAddress(
           @RequestBody Map<String, Object> addressDetails) {
        
        try {
            // 验证token并获取用户
            if(addressDetails.get("token") == null || addressDetails.get("addressid") == null || addressDetails.get("is_default") == null) {
                 return Utils.getErrorJson(400, "Invalid params");
            }
            String token = (String) addressDetails.get("token");
            Long addressid;
            try {
                addressid = Long.valueOf((String) addressDetails.get("addressid").toString());
            } catch (NumberFormatException e) {
                return Utils.getErrorJson(400, "Invalid address ID format");
            }
            Boolean is_default = (Boolean) addressDetails.get("is_default");

            User user = userRepository.findByToken(token);
            if (user == null) {
                  return Utils.getErrorJson(400, "Invalid token");
            }

            // 查找地址是否存在且属于该用户
            Address address = addressRepository.findByAddressidAndUser(addressid, user);
            if (address == null) {
                return Utils.getErrorJson(400, "Address not found or does not belong to user");
            }

            if (is_default) {
                // 将其他地址设置为非默认
                addressRepository.updateOtherAddressesDefaultStatus(user.getUserId(), address.getAddressid());
                // 设置当前地址为默认
                address.setDefault(true);
            } else {
                // 如果要取消默认状态，确保用户至少有一个默认地址
                List<Address> userAddresses = addressRepository.findByUser(user);
                long defaultAddressCount = userAddresses.stream()
                    .filter(Address::isDefault)
                    .count();
                
                if (defaultAddressCount <= 1 && address.isDefault()) {
                    return Utils.getErrorJson(400, "Cannot unset the only default address");
                }
                address.setDefault(false);
            }

            addressRepository.save(address);
            
            return Utils.getResponseJson("Address default status updated successfully");
            
        } catch (Exception e) {
            logger.error("Error setting default address: ", e);
            return Utils.getErrorJson(500, "Internal server error");
        }
    }

    @PostMapping("/edit_address")
    @Transactional
    public String editAddress(@RequestBody Map<String, Object> addressDetails) {
        // 验证token
        if(addressDetails.get("token") == null){
            return Utils.getErrorJson(400, "Missing token");
        }
        String token = (String) addressDetails.get("token");
        User user = userRepository.findByToken(token);
        if (user == null || user.getUserId() == null) {
            return Utils.getErrorJson(401, "Invalid token");
        }

        // 验证addressid
        if(addressDetails.get("addressid") == null) {
            return Utils.getErrorJson(400, "Missing addressid");
        }
        Long addressid;
        try {
            addressid = Long.valueOf(addressDetails.get("addressid").toString());
        } catch (NumberFormatException e) {
            return Utils.getErrorJson(400, "Invalid address ID format");
        }

        // 验证地址是否存在且属于该用户
        Address address = addressRepository.findByAddressidAndUser(addressid, user);
        if (address == null) {
            return Utils.getErrorJson(400, "Address not found or does not belong to user");
        }

        // 验证必填字段
        if (addressDetails.get("province") == null || addressDetails.get("city") == null ||
            addressDetails.get("district") == null || addressDetails.get("detail_address") == null ||
            addressDetails.get("phone_number") == null || addressDetails.get("consignee") == null) {
            return Utils.getErrorJson(400, "Missing required address fields");
        }

        // 更新地址信息
        address.setProvince((String) addressDetails.get("province"));
        address.setCity((String) addressDetails.get("city"));
        address.setDistrict((String) addressDetails.get("district"));
        address.setDetailAddress((String) addressDetails.get("detail_address"));
        address.setPhoneNumber((String) addressDetails.get("phone_number"));
        address.setConsignee((String) addressDetails.get("consignee"));
        
        // 处理默认地址设置
        Boolean isDefault = (Boolean) addressDetails.get("is_default");
        if (isDefault != null && isDefault && !address.isDefault()) {
            // 如果设置为默认地址，更新其他地址的默认状态
            addressRepository.updateOtherAddressesDefaultStatus(user.getUserId(), address.getAddressid());
            address.setDefault(true);
        } else if (isDefault != null && !isDefault && address.isDefault()) {
            // 如果要取消默认状态，确保用户至少有一个默认地址
            List<Address> userAddresses = addressRepository.findByUser(user);
            long defaultAddressCount = userAddresses.stream()
                .filter(Address::isDefault)
                .count();
            
            if (defaultAddressCount <= 1) {
                return Utils.getErrorJson(400, "Cannot unset the only default address");
            }
            address.setDefault(false);
        }

        try {
            addressRepository.save(address);
            logger.info("address updated -> " + address.toString());
            return Utils.getResponseJson("Address updated successfully");
        } catch (Exception e) {
            logger.error("Error updating address: ", e);
            return Utils.getErrorJson(500, "Internal server error");
        }
    }

    @PostMapping("/del_address")
    @Transactional
    public String deleteAddress(@RequestBody Map<String, Object> requestParams) {
        // 验证参数
        if (requestParams.get("token") == null) {
            return Utils.getErrorJson(400, "Token is required");
        }
        if (requestParams.get("addressid") == null) {
            return Utils.getErrorJson(400, "Address ID is required");
        }

        String token = (String) requestParams.get("token");
        Long addressId;
        try {
            addressId = Long.valueOf(requestParams.get("addressid").toString());
        } catch (NumberFormatException e) {
            return Utils.getErrorJson(400, "Invalid address ID format");
        }

        // 验证用户
        User user = userRepository.findByToken(token);
        if (user == null || user.getUserId() == null) {
            return Utils.getErrorJson(401, "Invalid token");
        }

        // 查找并验证地址
        Address address = addressRepository.findByAddressidAndUser(addressId, user);
        if (address == null) {
            return Utils.getErrorJson(404, "Address not found or not owned by user");
        }

        try {
            // 删除地址
            addressRepository.delete(address);
            logger.info("Address deleted -> " + address.toString());
            return Utils.getResponseJson("Address deleted successfully");
        } catch (Exception e) {
            logger.error("Error deleting address: " + e.getMessage(), e);
            return Utils.getErrorJson(500, "Error deleting address");
        }
    }

    @PostMapping("/set_order")
    @Transactional
    public String setOrder(@RequestBody OrderRequest orderRequest) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(orderRequest.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 验证地址
            Address address = addressRepository.findByAddressidAndUser(orderRequest.getAddressId(), user);
            if (address == null) {
                return Utils.getErrorJson(400, "Address not found or does not belong to user");
            }

            // 创建订单
            Order order = new Order();
            order.setUser(user);
            order.setAddress(address);
            order.setAmount(orderRequest.getTotalAmount());
            // order.setActualAmount(orderRequest.getTotalAmount()); // 实际支付金额，可以根据需求调整
            order.setPayOrderNumber(snowflakeIdGenerator.generateOrderNumber());
            order.setStatus("PENDING_PAYMENT");
            order = orderRepository.save(order);

            // 保存照片信息
            if (orderRequest.getPhotos() != null) {
                for (OrderRequest.PhotoInfo photoInfo : orderRequest.getPhotos()) {
                    Photo photo = new Photo();
                    photo.setOrder(order);
                    photo.setImageUrl(photoInfo.getImage_url());
                    photo.setResolution(photoInfo.getResolution());
                    photo.setSize(photoInfo.getSize());
                    photo.setMaterial(photoInfo.getMaterial());
                    photo.setNfcQrcode(photoInfo.getNfc_qrcode());
                    photo.setAmount(photoInfo.getAmount());
                    photo.setUser(user);
                    photoRepository.save(photo);
                }
            }

            Map<String, Object> response = new HashMap<>();
            response.put("message", "Order created successfully");
            response.put("orderId", order.getOrderId());
            response.put("payOrderNumber", order.getPayOrderNumber());
            return Utils.getResponseJson(response);
        } catch (Exception e) {
            logger.error("Error creating order: ", e);
            return Utils.getErrorJson(500, "Internal server error");
        }
    }

    @GetMapping("/get_my_some_order")
    public String getMyPendingOrders(@RequestParam String token) {
        try {
            // 根据token获取用户
            User user = userRepository.findByToken(token);
            if (user == null) {
                return Utils.getErrorJson(401, "Invalid token");
            }

            // 获取待付款和待收货订单数量
            Long pendingPaymentCount = orderRepository.countPendingPaymentOrders(user);
            Long pendingDeliveryCount = orderRepository.countPendingDeliveryOrders(user);

            // 返回结果
            Map<String, Long> result = Map.of(
                "pendingPaymentCount", pendingPaymentCount,
                "pendingDeliveryCount", pendingDeliveryCount
            );

            return Utils.getResponseJson(result);
        } catch (Exception e) {
            logger.error("Error getting pending orders: ", e);
            return Utils.getErrorJson(500, "Failed to get pending orders");
        }
    }

    @GetMapping("/get_my_all_need_pay")
    public String getMyAllNeedPayOrders(@RequestParam String token) {
        try {
            // 根据token获取用户
            User user = userRepository.findByToken(token);
            if (user == null) {
                return Utils.getErrorJson(401, "Invalid token");
            }

            // 获取所有待付款订单
            List<Order> pendingOrders = orderRepository.findAllPendingPaymentOrders(user);
            
            // 构建返回数据，包含订单信息和对应的照片信息
            List<Map<String, Object>> resultList = new ArrayList<>();
            
            for (Order order : pendingOrders) {
                Map<String, Object> orderMap = new HashMap<>();
                
                // 订单基本信息
                orderMap.put("orderId", order.getOrderId());
                orderMap.put("orderNumber", order.getOrderNumber());
                orderMap.put("amount", order.getAmount());
                orderMap.put("orderTime", order.getOrderTime());
                orderMap.put("status", order.getStatus());
                orderMap.put("payOrderNumber", order.getPayOrderNumber());
                // 收货地址信息
                Address address = order.getAddress();
                Map<String, Object> addressMap = new HashMap<>();
                addressMap.put("addressId", address.getAddressid());
                addressMap.put("province", address.getProvince());
                addressMap.put("city", address.getCity());
                addressMap.put("district", address.getDistrict());
                addressMap.put("detailAddress", address.getDetailAddress());
                addressMap.put("phoneNumber", address.getPhoneNumber());
                addressMap.put("consignee", address.getConsignee());
                orderMap.put("address", addressMap);
                
                // 获取订单对应的照片信息
                List<Photo> photos = photoRepository.findByOrderOrderByCreateTimeDesc(order);
                List<Map<String, Object>> photoList = new ArrayList<>();
                if(photos.size() > 0){
                    Map<String, Object> photoMap = new HashMap<>();
                    Photo photo = photos.get(0);
              
                    photoMap.put("photoId", photo.getPhotoId());
                    photoMap.put("imageUrl", Utils.getQiniuPrivateDownloadUrl(photo.getImageUrl()));
                    photoMap.put("imagethumbnailUrl", Utils.getQiniuPrivateDownloadUrlThumbil(photo.getImageUrl()));
                    photoMap.put("thumbnailUrl", Utils.getQiniuVideoThumbil(photo.getVideoUrl()));
                    photoMap.put("videoUrl", Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl()));
                    photoMap.put("amount", photo.getAmount());
                    photoMap.put("size", photo.getSize());
                    photoMap.put("material", photo.getMaterial());
                    photoMap.put("resolution", photo.getResolution());
                    photoList.add(photoMap);
                }
                // for (Photo photo : photos) {
                //     Map<String, Object> photoMap = new HashMap<>();
                //     photoMap.put("photoId", photo.getPhotoId());
                //     photoMap.put("imageUrl", photo.getImageUrl());
              
                //     photoMap.put("amount", photo.getAmount());
                //     photoMap.put("size", photo.getSize());
                //     photoMap.put("material", photo.getMaterial());
                //     photoMap.put("resolution", photo.getResolution());
                //     photoList.add(photoMap);
                // }
                
                orderMap.put("photos", photoList);
                orderMap.put("photoCnt" , photos.size());
                resultList.add(orderMap);
            }

            return Utils.getResponseJson(resultList);
        } catch (Exception e) {
            logger.error("Error getting pending payment orders: ", e);
            return Utils.getErrorJson(500, "Failed to get pending payment orders");
        }
    }

    @PostMapping("/get_order_photos")
    public String getOrderPhotos(@RequestBody OrderPhotosRequest request) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 获取订单信息
            Order order = orderRepository.findById(request.getOrderId()).orElse(null);
            if (order == null || !order.getUser().getUserId().equals(user.getUserId())) {
                return Utils.getErrorJson(400, "Order not found or does not belong to user");
            }

            Map<String, Object> result = new HashMap<>();
            
            // 订单基本信息
            Map<String, Object> orderMap = new HashMap<>();
            orderMap.put("orderId", order.getOrderId());
            orderMap.put("amount", order.getAmount());
            orderMap.put("actualAmount", order.getActualAmount());
            orderMap.put("orderTime", order.getOrderTime());
            orderMap.put("status", order.getStatus());
            result.put("order", orderMap);
            
            // 收货地址信息
            Address address = order.getAddress();
            Map<String, Object> addressMap = new HashMap<>();
            addressMap.put("addressId", address.getAddressid());
            addressMap.put("province", address.getProvince());
            addressMap.put("city", address.getCity());
            addressMap.put("district", address.getDistrict());
            addressMap.put("detailAddress", address.getDetailAddress());
            addressMap.put("phoneNumber", address.getPhoneNumber());
            addressMap.put("consignee", address.getConsignee());
            result.put("address", addressMap);
            
            // 照片信息
            List<Photo> photos = photoRepository.findByOrderOrderByCreateTimeDesc(order);
            List<Map<String, Object>> photoList = new ArrayList<>();
            for (Photo photo : photos) {
                Map<String, Object> photoMap = new HashMap<>();
                photoMap.put("photoId", photo.getPhotoId());
                photoMap.put("imageUrl", Utils.getQiniuPrivateDownloadUrl(photo.getImageUrl()));
                photoMap.put("imagethumbnailUrl", Utils.getQiniuPrivateDownloadUrlThumbil(photo.getImageUrl()));
                photoMap.put("thumbnailUrl", Utils.getQiniuVideoThumbil(photo.getVideoUrl()));
                photoMap.put("videoUrl", Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl()));
                photoMap.put("amount", photo.getAmount());
                photoMap.put("size", photo.getSize());
                photoMap.put("material", photo.getMaterial());
                photoMap.put("resolution", photo.getResolution());
                photoList.add(photoMap);
            }
            result.put("photos", photoList);
            result.put("photoCnt", photos.size());

            return Utils.getResponseJson(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Utils.getErrorJson(500, "Server error: " + e.getMessage());
        }
    }

    @PostMapping("/get_my_pay_order")
    public String getMyPayOrder(@RequestBody MyPayOrderRequest request) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 创建分页请求
            Pageable pageable = PageRequest.of(request.getStart(), request.getPage(), Sort.by(Sort.Direction.DESC, "orderTime"));
            
            // 获取已支付订单
            Page<Order> orderPage = orderRepository.findPaidOrdersWithPagination(user, pageable);
            
            Map<String, Object> result = new HashMap<>();
            List<Map<String, Object>> orderList = new ArrayList<>();
            
            for (Order order : orderPage.getContent()) {
                Map<String, Object> orderMap = new HashMap<>();
                
                // 订单基本信息
                orderMap.put("orderId", order.getOrderId());
                orderMap.put("amount", order.getAmount());
                orderMap.put("actualAmount", order.getActualAmount());
                orderMap.put("orderTime", order.getOrderTime());
                orderMap.put("status", order.getStatus());
                orderMap.put("orderNumber", order.getOrderNumber());
                // 收货地址信息
                Address address = order.getAddress();
                Map<String, Object> addressMap = new HashMap<>();
                addressMap.put("addressId", address.getAddressid());
                addressMap.put("province", address.getProvince());
                addressMap.put("city", address.getCity());
                addressMap.put("district", address.getDistrict());
                addressMap.put("detailAddress", address.getDetailAddress());
                addressMap.put("phoneNumber", address.getPhoneNumber());
                addressMap.put("consignee", address.getConsignee());
                orderMap.put("address", addressMap);
                
                // 获取第一张照片信息
                List<Photo> photos = photoRepository.findByOrderOrderByCreateTimeDesc(order);
                if (!photos.isEmpty()) {
                    Photo photo = photos.get(0);
                    Map<String, Object> photoMap = new HashMap<>();
                    photoMap.put("photoId", photo.getPhotoId());
                    photoMap.put("imageUrl", Utils.getQiniuPrivateDownloadUrl(photo.getImageUrl()));
                    photoMap.put("imagethumbnailUrl", Utils.getQiniuPrivateDownloadUrlThumbil(photo.getImageUrl()));
                    photoMap.put("thumbnailUrl", Utils.getQiniuVideoThumbil(photo.getVideoUrl()));
                    photoMap.put("videoUrl", Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl()));
                    photoMap.put("amount", photo.getAmount());
                    photoMap.put("size", photo.getSize());
                    photoMap.put("material", photo.getMaterial());
                    photoMap.put("resolution", photo.getResolution());
                    photoMap.put("nfcQrcode", photo.getNfcQrcode());
                    orderMap.put("photo", photoMap);
                    
                }
                
                orderMap.put("photoCnt", photos.size());
                orderList.add(orderMap);
            }
            
            // 添加分页信息
            result.put("orders", orderList);
            result.put("totalPages", orderPage.getTotalPages());
            result.put("totalElements", orderPage.getTotalElements());
            result.put("currentPage", orderPage.getNumber());
            result.put("size", orderPage.getSize());

            return Utils.getResponseJson(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Utils.getErrorJson(500, "Server error: " + e.getMessage());
        }
    }

    @PostMapping("/get_my_all_order")
    public String getMyAllOrder(@RequestBody AllOrdersRequest request) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 创建分页请求
            Pageable pageable = PageRequest.of(request.getStart(), request.getPage(), Sort.by(Sort.Direction.DESC, "orderTime"));
            
            // 获取所有已支付订单
            Page<Order> orderPage = orderRepository.findAllPaidOrdersWithPagination(user, pageable);
            
            Map<String, Object> result = new HashMap<>();
            List<Map<String, Object>> orderList = new ArrayList<>();
            
            for (Order order : orderPage.getContent()) {
                Map<String, Object> orderMap = new HashMap<>();
                
                // 订单基本信息
                orderMap.put("orderId", order.getOrderId());
                orderMap.put("orderNumber", order.getOrderNumber());
                orderMap.put("amount", order.getAmount());
                orderMap.put("actualAmount", order.getActualAmount());
                orderMap.put("orderTime", order.getOrderTime());
                orderMap.put("status", order.getStatus());
                
                // 收货地址信息
                Address address = order.getAddress();
                Map<String, Object> addressMap = new HashMap<>();
                addressMap.put("addressId", address.getAddressid());
                addressMap.put("province", address.getProvince());
                addressMap.put("city", address.getCity());
                addressMap.put("district", address.getDistrict());
                addressMap.put("detailAddress", address.getDetailAddress());
                addressMap.put("phoneNumber", address.getPhoneNumber());
                addressMap.put("consignee", address.getConsignee());
                orderMap.put("address", addressMap);
                
                // 获取第一张照片信息
                List<Photo> photos = photoRepository.findByOrderOrderByCreateTimeDesc(order);
                if (!photos.isEmpty()) {
                    Photo photo = photos.get(0);
                    Map<String, Object> photoMap = new HashMap<>();
                    photoMap.put("photoId", photo.getPhotoId());
                      photoMap.put("imageUrl", Utils.getQiniuPrivateDownloadUrl(photo.getImageUrl()));
                photoMap.put("imagethumbnailUrl", Utils.getQiniuPrivateDownloadUrlThumbil(photo.getImageUrl()));
                    photoMap.put("thumbnailUrl", Utils.getQiniuVideoThumbil(photo.getVideoUrl()));
                    photoMap.put("videoUrl", Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl()));
                    photoMap.put("amount", photo.getAmount());
                    photoMap.put("size", photo.getSize());
                    photoMap.put("material", photo.getMaterial());
                    photoMap.put("resolution", photo.getResolution());
                    orderMap.put("photo", photoMap);
                }
                
                orderMap.put("photoCnt", photos.size());
                orderList.add(orderMap);
            }
            
            // 添加分页信息
            result.put("orders", orderList);
            result.put("totalPages", orderPage.getTotalPages());
            result.put("totalElements", orderPage.getTotalElements());
            result.put("currentPage", orderPage.getNumber());
            result.put("size", orderPage.getSize());

            return Utils.getResponseJson(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Utils.getErrorJson(500, "Server error: " + e.getMessage());
        }
    }

    @PostMapping("/already_recive_myphoto")
    @Transactional
    public String receiveOrder(@RequestBody ReceiveOrderRequest request) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 获取订单信息
            Order order = orderRepository.findById(request.getOrderId()).orElse(null);
            if (order == null) {
                return Utils.getErrorJson(400, "Order not found");
            }

            // 验证订单归属
            if (!order.getUser().getUserId().equals(user.getUserId())) {
                return Utils.getErrorJson(400, "Order does not belong to user");
            }

            // 验证订单状态
            if (order.getStatus().equals("SIGNED")) {
                return Utils.getResponseJson("Order already signed");
            }

            // 更新订单状态为已签收
            order.setStatus("SIGNED");
            orderRepository.save(order);

            return Utils.getResponseJson("Order signed successfully");
        } catch (Exception e) {
            e.printStackTrace();
            return Utils.getErrorJson(500, "Server error: " + e.getMessage());
        }
    }

    @PostMapping("/get_my_photo")
    public String getMyPhotos(@RequestBody MyPhotosRequest request) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 创建分页请求
            Pageable pageable = PageRequest.of(request.getStart(), request.getPage(), Sort.by(Sort.Direction.DESC, "createTime"));
            
            // 获取所有已支付订单的照片
            Page<Photo> photoPage = photoRepository.findUserPaidPhotosWithPagination(user, pageable);
            
            Map<String, Object> result = new HashMap<>();
            List<Map<String, Object>> photoList = new ArrayList<>();
            logger.info("myphoto -> "+photoPage.getContent().size()+" start "+ 
                request.getStart()+" page "+ request.getPage()+" total "+photoPage.getTotalElements());
            for (Photo photo : photoPage.getContent()) {
                Map<String, Object> photoMap = new HashMap<>();
                photoMap.put("photoId", photo.getPhotoId());
                photoMap.put("imageUrl", Utils.getQiniuPrivateDownloadUrl(photo.getImageUrl()));
                photoMap.put("imagethumbnailUrl", Utils.getQiniuPrivateDownloadUrlThumbil(photo.getImageUrl()));
                photoMap.put("thumbnailUrl", Utils.getQiniuVideoThumbil(photo.getVideoUrl()));
                photoMap.put("videoUrl", Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl()));
                photoMap.put("amount", photo.getAmount());
                photoMap.put("size", photo.getSize());
                photoMap.put("material", photo.getMaterial());
                photoMap.put("resolution", photo.getResolution());
                photoMap.put("createTime", photo.getCreateTime());
                photoMap.put("nfcQrcode", photo.getNfcQrcode());
                
                // 添加订单信息
                Order order = photo.getOrder();
                Map<String, Object> orderMap = new HashMap<>();
                orderMap.put("orderId", order.getOrderId());
                orderMap.put("orderNumber", order.getOrderNumber());
                orderMap.put("orderTime", order.getOrderTime());
                orderMap.put("status", order.getStatus());
                photoMap.put("order", orderMap);
                
                photoList.add(photoMap);
            }
            
            // 添加分页信息
            result.put("photos", photoList);
            result.put("totalPages", photoPage.getTotalPages());
            result.put("totalElements", photoPage.getTotalElements());
            result.put("currentPage", photoPage.getNumber());
            result.put("size", photoPage.getSize());

            return Utils.getResponseJson(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Utils.getErrorJson(500, "Server error: " + e.getMessage());
        }
    }

    @PostMapping("/upload_video_success")
    @Transactional
    public String uploadVideoSuccess(@RequestBody UploadVideoRequest request) {
        try {
            // 验证token和用户
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(400, "Invalid token");
            }

            // 获取照片信息
            Photo photo = photoRepository.findById(request.getPhotoId()).orElse(null);
            if (photo == null) {
                return Utils.getErrorJson(400, "Photo not found");
            }

            // 验证照片归属
            if (!photo.getOrder().getUser().getUserId().equals(user.getUserId())) {
                return Utils.getErrorJson(400, "Photo does not belong to user");
            }

            // 更新视频URL
            photo.setVideoUrl(request.getVideoUrl());
            photoRepository.save(photo);
            
            // 生成视频访问URL和缩略图URL
            String videoUrl = Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl());
            // String thumbnailUrl = Utils.getQiniuVideoThumbil(photo.getVideoUrl());
            
            Map<String, String> result = new HashMap<>();
            result.put("videoUrl", videoUrl);
            result.put("photoId", photo.getPhotoId().toString());
            // result.put("thumbnailUrl", thumbnailUrl);
            
            return Utils.getResponseJson(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Utils.getErrorJson(500, "Server error: " + e.getMessage());
        }
    }

    @PostMapping("/get_photo")
    public String getPhoto(@RequestBody GetPhotoRequest request, HttpServletRequest httpRequest) {
        PhotoAccessLog accessLog = new PhotoAccessLog();
        accessLog.setAccessTime(LocalDateTime.now());
        accessLog.setIpAddress(getClientIp(httpRequest));
        accessLog.setUserAgent(httpRequest.getHeader("User-Agent"));
        
        try {
            Long photoId = Long.parseLong(request.getPhotoId());
            Long userId = Long.parseLong(request.getUserId());
            accessLog.setPhotoId(photoId);
            accessLog.setUserId(userId);

            // 1. 检查访问频率限制
            LocalDateTime checkTime = LocalDateTime.now().minusMinutes(1);
            if (photoAccessLogRepository.countRecentAccessesByIp(accessLog.getIpAddress(), checkTime) > 40) {
                accessLog.setIsSuccess(false);
                accessLog.setFailReason("访问频率过高");
                photoAccessLogRepository.save(accessLog);
                return Utils.getErrorJson(429, "访问频率过高，请稍后再试");
            }

            // 2. 查找照片
            Optional<Photo> photoOpt = photoRepository.findById(photoId);
            if (photoOpt.isEmpty()) {
                accessLog.setIsSuccess(false);
                accessLog.setFailReason("照片不存在");
                photoAccessLogRepository.save(accessLog);
                return Utils.getErrorJson(404, "照片不存在");
            }

            Photo photo = photoOpt.get();
            User user = photo.getUser();
            
            // 3. 验证用户ID和权限
            if (user == null || !userId.equals(user.getUserId())) {
                accessLog.setIsSuccess(false);
                accessLog.setFailReason("无权访问");
                photoAccessLogRepository.save(accessLog);
                return Utils.getErrorJson(403, "无权访问该照片");
            }

            // 4. 验证密码
            String photoPassword = user.getPhotoPassword();
            if (photoPassword != null && !photoPassword.isEmpty()) {
                if (!photoPassword.equals(request.getPassword())) {
                    accessLog.setIsSuccess(false);
                    accessLog.setFailReason("密码错误");
                    photoAccessLogRepository.save(accessLog);
                    return Utils.getErrorJson(401, "密码错误");
                }
            }

            // 5. 返回照片信息
            Map<String, Object> photoData = new HashMap<>();
            photoData.put("id", photo.getPhotoId());
            photoData.put("imageUrl", Utils.getQiniuPrivateDownloadUrl(photo.getImageUrl()));
            photoData.put("thumbnailUrl", Utils.getQiniuVideoThumbil(photo.getVideoUrl()));
            photoData.put("videoUrl", Utils.getQiniuPrivateDownloadUrl(photo.getVideoUrl()));
            photoData.put("amount", photo.getAmount());
            photoData.put("nfcQrcode", photo.getNfcQrcode());
            
            Map<String, Object> data = new HashMap<>();
            data.put("photo", photoData);

            // 记录成功访问
            accessLog.setIsSuccess(true);
            photoAccessLogRepository.save(accessLog);
            
            return Utils.getResponseJson(data);
        } catch (NumberFormatException e) {
            accessLog.setIsSuccess(false);
            accessLog.setFailReason("无效的ID格式");
            photoAccessLogRepository.save(accessLog);
            return Utils.getErrorJson(400, "无效的照片ID格式");
        } catch (Exception e) {
            accessLog.setIsSuccess(false);
            accessLog.setFailReason(e.getMessage());
            photoAccessLogRepository.save(accessLog);
            e.printStackTrace();
            return Utils.getErrorJson(500, "服务器错误：" + e.getMessage());
        }
    }

    @PostMapping("/set_photo_password")
    public String setPhotoPassword(@RequestBody SetPhotoPasswordRequest request) {
        try {
            // 验证token
            User user = userRepository.findByToken(request.getToken());
            if (user == null) {
                return Utils.getErrorJson(401, "用户未找到");
            }

            // 设置密码
            user.setPhotoPassword(request.getPhotoPassword());
            userRepository.save(user);

            logger.info("User {} set photo password successfully", user.getUserId());
            return Utils.getResponseJson(new JSONObject().put("message", "密码设置成功"));
        } catch (Exception e) {
            logger.error("Failed to set photo password", e);
            return Utils.getErrorJson(500, "设置失败：" + e.getMessage());
        }
    }

    @GetMapping("/get_photo_password")
    public String getPhotoPassword(@RequestParam String token) {
        try {
            // 验证token
            User user = userRepository.findByToken(token);
            if (user == null) {
                return Utils.getErrorJson(401, "用户未找到");
            }

            // 返回密码
            String password = user.getPhotoPassword();
            if (password == null) {
                password = ""; // 如果没有设置密码，返回空字符串
            }

            logger.info("User {} get photo password", user.getUserId());
            return Utils.getResponseJson(new JSONObject().put("photoPassword", password));
        } catch (Exception e) {
            logger.error("Failed to get photo password", e);
            return Utils.getErrorJson(500, "获取失败：" + e.getMessage());
        }
    }

    @PostMapping("/create_pay")
    public String createPay(@RequestBody Map<String, String> request) {
        try {
            String token = request.get("token");
            String orderId = request.get("orderId");
            String payOrderNumber = request.get("payOrderNumber");
            logger.info("[PAY] "+"token "+token+" orderId "+orderId+" payOrderNumber "+payOrderNumber);
            
            // 参数验证
            if (token == null || token.isEmpty()) {
                logger.error("[PAY] token is empty");
                return Utils.getErrorJson(400, "token不能为空");
            }
            if (orderId == null || orderId.isEmpty()) {
                logger.error("[PAY] orderId is empty");
                return Utils.getErrorJson(400, "订单ID不能为空");
            }
            if (payOrderNumber == null || payOrderNumber.isEmpty()) {
                logger.error("[PAY] payOrderNumber is empty");
                return Utils.getErrorJson(400, "支付订单号不能为空");
            }
            
            // 验证token
            User user = userRepository.findByToken(token);
            if (user == null) {
                logger.error("[PAY] "+"user not found");
                return Utils.getErrorJson(401, "用户未找到");
            }
            logger.info("[PAY] "+"user "+user.getUserId());
            // 查找订单，同时验证orderId和payOrderNumber
            Optional<Order> orderOpt = orderRepository.findByOrderIdAndPayOrderNumber(Long.parseLong(orderId), payOrderNumber);
            if (orderOpt.isEmpty()) {
                logger.error("[PAY] "+"order not found or payOrderNumber mismatch");
                return Utils.getErrorJson(404, "订单不存在或支付订单号不匹配");
            }

            Order order = orderOpt.get();
            logger.info("[PAY] "+"order "+order.toString());
            // 验证订单所属用户
            if (!order.getUser().getUserId().equals(user.getUserId())) {
                 logger.error("[PAY] "+"无权访问该订单");
                return Utils.getErrorJson(403, "无权访问该订单");
            }


            // 创建预支付订单
            JSONObject payInfo = wxPayService.createPrePayOrder(order, user.getOpenid());
            
            // 更新订单状态
            order.setStatus("paying");
            orderRepository.save(order);

            logger.info("Created pay order for orderId: {}", orderId);
            return Utils.getResponseJson(payInfo);
            // return Utils.getResponseJson("success"); //xhc test
        } catch (Exception e) {
            logger.error("Failed to create pay order", e);
            return Utils.getErrorJson(500, "创建支付订单失败：" + e.getMessage());
        }
    }

    @PostMapping("/wx_pay_notify")
    public String wxPayNotify(@RequestBody String notifyData, @RequestHeader("Wechatpay-Signature") String signature) {
        try {
            logger.info("[PAY] "+"notifyData "+notifyData+" signature "+signature);
            // 验证签名
            if (!verifySignature(notifyData, signature)) {
                return "FAIL";
            }
            JSONObject notify = new JSONObject(notifyData);
            JSONObject resource = notify.getJSONObject("resource");
            
            // 解密通知数据
            String ciphertext = resource.getString("ciphertext");
            String nonce = resource.getString("nonce");
            String associatedData = resource.getString("associated_data");
            
            String plaintext = decryptResource(ciphertext, nonce, associatedData, GlobalConfig.PAY_API_v3);
            JSONObject decryptedResource = new JSONObject(plaintext);
            logger.info("[PAY] Decrypted resource: {}", decryptedResource.toString());
            
            // 从解密后的数据中获取attach
            JSONObject attachData = new JSONObject(decryptedResource.getString("attach"));
            String tradeState = notify.getString("event_type");
            Long orderId = attachData.getLong("orderId");  
            String payOrderNumber = attachData.getString("payOrderNumber");
            BigDecimal amount = BigDecimal.valueOf(attachData.getDouble("amount"));
            
            logger.info("[PAY] orderId={}, tradeState={}, payOrderNumber={}, amount={}, decryptedResource={}", 
                orderId, tradeState, payOrderNumber, amount, decryptedResource);
            // 解析通知数据
            // JSONObject notify = new JSONObject(notifyData);
            // String orderId = notify.getString("out_trade_no");
          
            // logger.info("[PAY] "+"orderId "+orderId+" tradeState "+tradeState);
            // 查找订单
            Optional<Order> orderOpt = orderRepository.findById(orderId);
            if (orderOpt.isEmpty()) {
                logger.error("[PAY] Order not found: {}", orderId);
                return "FAIL";
            }

            Order order = orderOpt.get();

            // 更新订单状态
            if ("TRANSACTION.SUCCESS".equals(tradeState)) {
                order.setStatus("paid");
                order.setPayTime(LocalDateTime.now());
                order.setActualAmount(amount);
                orderRepository.save(order);
                logger.info("[PAY] Order paid successfully: {}", orderId+" "+amount);
            } else if ("REFUND".equals(tradeState)) {
                order.setStatus("refunded");
                orderRepository.save(order);
                logger.info("[PAY] Order refunded: {}", orderId);
            }

            // 解析attach中的JSON数据
          

            return "SUCCESS";
        } catch (Exception e) {
            logger.error("Failed to process pay notify", e);
            return "FAIL";
        }
    }

    private boolean verifySignature(String notifyData, String signature) {
        try {
            // 这里实现微信支付通知签名验证逻辑
            // 使用微信支付平台证书验证签名
            // 具体实现参考微信支付文档
            return true; // 临时返回true，需要实现实际的验证逻辑
        } catch (Exception e) {
            logger.error("Failed to verify signature", e);
            return false;
        }
    }

    /**
     * 解密回调通知数据
     * @param ciphertext 密文
     * @param nonce 随机串
     * @param associatedData 附加数据
     * @param apiV3Key API v3密钥
     * @return 解密后的明文
     */
    private String decryptResource(String ciphertext, String nonce, String associatedData, String apiV3Key) {
        try {
            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding");
            
            byte[] key = apiV3Key.getBytes(StandardCharsets.UTF_8);
            byte[] nonceBytes = nonce.getBytes(StandardCharsets.UTF_8);
            byte[] associatedDataBytes = associatedData == null ? new byte[0] : associatedData.getBytes(StandardCharsets.UTF_8);
            
            // 初始化GCM参数
            GCMParameterSpec spec = new GCMParameterSpec(128, nonceBytes);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKeySpec, spec);
            
            // 设置附加数据
            if (associatedDataBytes.length > 0) {
                cipher.updateAAD(associatedDataBytes);
            }
            
            // 解密
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
            return new String(decrypted, StandardCharsets.UTF_8);
            
        } catch (Exception e) {
            logger.error("[PAY] Failed to decrypt resource", e);
            throw new RuntimeException("Failed to decrypt resource", e);
        }
    }

    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
